#include "msp_adc.h"
// stm32 ll库
#include "stm32f1xx_ll_adc.h"
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_gpio.h"

#define SOLAR_ADC_PIN                       LL_GPIO_PIN_6
#define SOLAR_ADC_PORT                      GPIOA
#define BAT_ADC_PIN                         LL_GPIO_PIN_7
#define BAT_ADC_PORT                        GPIOA

/* ADC1 init function */
void MSP_ADC1_Init(void)
{
    /*
    //结构体与时钟
    LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
    LL_ADC_InitTypeDef ADC_InitStruct = {0};
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    // LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
    // LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    //初始化adc引脚
    // PA6   ------> ADC1_IN6
    // PA7   ------> ADC1_IN7
    GPIO_InitStruct.Pin = SOLAR_ADC_PIN;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    LL_GPIO_Init(SOLAR_ADC_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = BAT_ADC_PIN;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    LL_GPIO_Init(BAT_ADC_PORT, &GPIO_InitStruct);
    //设置ADC外设
    ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;                                    //触发源为软件触发
    ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;                           //转换序列所有通道
    ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;                                     //序列连续转换
    ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;                                  //DMA搬运有限模式
    ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;                                   //数据无覆盖保护
    LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);                                                     //初始化ADC
    LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, \
                                        LL_ADC_SAMPLINGTIME_12CYCLES_5);                            //设置所有通道的转换周期
    LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_GRP_REGULAR_CONTINUED);                            //启用过采样功能
    LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_16, LL_ADC_OVS_SHIFT_RIGHT_4);       //过采样16次,保留高12位
    LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);                    //序列扫描方向为正向扫描
    LL_ADC_SetCommonFrequencyMode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_FREQ_MODE_LOW);      //ADC时钟频率为低速模式
    LL_ADC_DisableIT_EOC(ADC1);                                                                     //关闭通道转换完成中断
    LL_ADC_DisableIT_EOS(ADC1);                                                                     //关闭队列转换完成中断
    ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;                                              //使用12bit转换精度
    ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;                                         //数据格式右对齐
    ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;                                              //不使用低功耗模式
    LL_ADC_Init(ADC1, &ADC_InitStruct);                                                             //初始化ADC
    LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_ASYNC);                                                      //设置ADC时钟源
    LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_ASYNC_DIV16);                //设置ADC时钟源分频
    LL_ADC_EnableInternalRegulator(ADC1);                                                           //使能内部运算放大器
    uint32_t wait_loop_index;                                                                       //延时等待ADC内部初始化完成
    wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
    while(wait_loop_index != 0) wait_loop_index--;
    LL_ADC_StartCalibration(ADC1);                                                                  //ADC开始校准
    while(LL_ADC_IsCalibrationOnGoing(ADC1));                                                       //等待ADC校准完成
    */
}

/* ADC2 init function */
void MSP_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC2);

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
  /**ADC2 GPIO Configuration
  PB1   ------> ADC2_IN9
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */

  /** Common config
  */
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
  ADC_InitStruct.SequencersScanMode = LL_ADC_SEQ_SCAN_DISABLE;
  LL_ADC_Init(ADC2, &ADC_InitStruct);
  ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
  ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
  ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
  LL_ADC_REG_Init(ADC2, &ADC_REG_InitStruct);

  /** Configure Regular Channel
  */
  LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_9);
  LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_1CYCLE_5);
  /* USER CODE BEGIN ADC2_Init 2 */

  /* USER CODE END ADC2_Init 2 */

}

/**
 * @brief 
 * 
 * @param ch 
 * @return float 
 */
float Msp_Adc_Conver(uint8_t ch)
{
    /*
    //设置转换目标通道
    switch(ch)
    {
        // 添加实际使用的ADC转换通道-----------------------------------------------------------------------------
        case 6: LL_ADC_REG_SetSequencerChannels(ADC1, LL_ADC_CHANNEL_6); break;
        case 7: LL_ADC_REG_SetSequencerChannels(ADC1, LL_ADC_CHANNEL_7); break;
        // ---------------------------------------------------------------------------------------------------
    }
    //开始转换
    LL_ADC_Enable(ADC1);                                                                            //ADC使能
    LL_ADC_REG_StartConversion(ADC1);                                                               //ADC1开始转换
    while(!LL_ADC_IsActiveFlag_EOC(ADC1));                                                          //等待转换完成
    LL_ADC_Disable(ADC1);                                                                           //ADC关闭
    return (float)(LL_ADC_REG_ReadConversionData32(ADC1) * 0.0089955);                              //转换成电压并返回
    */
    return (float)(LL_ADC_REG_ReadConversionData32(ADC1) * 0.0089955);                              //转换成电压并返回
}
